// Source file:
// G:\\5o_ano\\PCS2040\\desenvolvimento\\rose\\Servidor\\Roteamento\\GrafoLoader.java

package servidor.roteamento;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import comum.Localizacao;

public class GrafoLoader {

    private static final int MAXIMO_RESTRICOES = 3;

    private static final String CRUZAMENTO = "cruzamento";
    private static final String FINAL = "final";
    private static final String PONTE = "ponte";
    private static final String SUBMAPA = "submapa";

    private static final String TAG_VERTICES = "vertices";

    private Document document;

    /**
     * @roseuid 426D7C4E02DE
     */
    public GrafoLoader(String filename) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //      factory.setValidating(true);
        //      factory.setNamespaceAware(true);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            document = builder.parse(new File(filename));
        } catch (SAXException sxe) {
            // Error generated during parsing
            Exception x = sxe;
            if (sxe.getException() != null) {
                x = sxe.getException();
            }
            x.printStackTrace();
        } catch (ParserConfigurationException pce) {
            // Parser with specified options can't be built
            pce.printStackTrace();
        } catch (IOException ioe) {
            // I/O error
            ioe.printStackTrace();
        }
    }

    /**
     * @roseuid 42599EF50109
     */
    public Collection load() {

        Collection grafoHierarquico = new ArrayList();

        NodeList grafos = document.getDocumentElement().getChildNodes();
        for (int i = 0; i < grafos.getLength(); i++) {
            Node nodeGrafo = grafos.item(i);
            if (nodeGrafo.getNodeType() == Node.ELEMENT_NODE
                    && ((Element) nodeGrafo).getTagName().equalsIgnoreCase("grafo")) {
                String nome = ((Element) nodeGrafo).getAttribute("nome");
                int nivelHierarquico = Integer.parseInt(((Element) nodeGrafo).getAttribute("nivelHierarquico"));
                Grafo grafo = new Grafo(nome, nivelHierarquico);

                NodeList nodeList = nodeGrafo.getChildNodes();
                Node nodeVertices = nodeList.item(1);
                NodeList vertices = nodeVertices.getChildNodes();
                for (int j = 0; j < vertices.getLength(); j++) {
                    Node nodeVertice = vertices.item(j);
                    if (nodeVertice.getNodeType() == Node.ELEMENT_NODE
                            && ((Element) nodeVertice).getTagName().equalsIgnoreCase("vertice")) {
                        Element elementVertice = (Element) nodeVertice;
                        Vertice vertice = null;
                        if (elementVertice.getAttribute("tipo").equalsIgnoreCase(CRUZAMENTO)) {
                            vertice = new VerticeCruzamento();
                        } else if (elementVertice.getAttribute("tipo").equalsIgnoreCase(FINAL)) {
                            vertice = new VerticeFinal();
                        } else if (elementVertice.getAttribute("tipo").equalsIgnoreCase(PONTE)) {
                            vertice = new VerticePonte();
                        } else if (elementVertice.getAttribute("tipo").equalsIgnoreCase(SUBMAPA)) {
                            vertice = new VerticeSubMapa();
                        } else {
                            // TODO ERRO!!! Tipo de vértice inválido!
                        	System.out.println("ERRO");
                        }
                        vertice.setNome(elementVertice.getAttribute("nome"));
                        Localizacao localizacao = new Localizacao(Integer.parseInt(elementVertice.getAttribute("x")),
                                Integer.parseInt(elementVertice.getAttribute("y")), Integer.parseInt(elementVertice
                                        .getAttribute("andar")));
                        vertice.setLocalizacao(localizacao);
                        vertice.setGrafoQueContem(grafo);
                        grafo.addVertice(vertice);
                    }
                }

                Node nodeArcos = nodeList.item(3);
                NodeList arcos = nodeArcos.getChildNodes();
                for (int j = 0; j < arcos.getLength(); j++) {
                    Node nodeArco = arcos.item(j);
                    if (nodeArco.getNodeType() == Node.ELEMENT_NODE
                            && ((Element) nodeArco).getTagName().equalsIgnoreCase("arco")) {
                        Element elementArco = (Element) nodeArco;
                        Vertice vOrigem = grafo.getVertice(elementArco.getAttribute("origem"));
                        Vertice vDestino = grafo.getVertice(elementArco.getAttribute("destino"));
                        int[] custos = new int[MAXIMO_RESTRICOES];
                        NodeList custosList = elementArco.getChildNodes();
                        for (int k = 0; k < custosList.getLength(); k++) {
                            Node nodeCusto = custosList.item(k);
                            if (nodeCusto.getNodeType() == Node.ELEMENT_NODE
                                    && ((Element) nodeCusto).getTagName().equalsIgnoreCase("custo")) {
                                Element custo = (Element) nodeCusto;
                                int restricao = Integer.parseInt(custo.getAttribute("restricao"));
                                int valor = Integer.parseInt(custo.getAttribute("valor"));
                                custos[restricao] = valor;
                            }
                        }
                        VerticeAdjacente adjacente = new VerticeAdjacente(vDestino, custos);
                        vOrigem.addVerticeAdjacente(adjacente);
                    }
                }

                grafoHierarquico.add(grafo);
            }
        }
        
        // Ajustar refer�ncia do v�rtice submapa dos grafos de n�velHierarquico >= 1
        for (Iterator iter = grafoHierarquico.iterator(); iter.hasNext();) {
            Grafo grafo = (Grafo) iter.next();
            if (grafo.getNivelHierarquico() >= 1) {
                for (Iterator iter2 = grafoHierarquico.iterator(); iter2.hasNext();) {
                    Grafo grafo2 = (Grafo) iter2.next();
                    if (grafo2.getNivelHierarquico() == grafo.getNivelHierarquico() - 1) {
                        for(Iterator iter3 = grafo2.getVertices().iterator(); iter3.hasNext();) {
                            Vertice vertice = (Vertice) iter3.next();
                            if (vertice.getNome().equals(grafo.getNome()) && vertice instanceof VerticeSubMapa) {
                                grafo.setVerticeQueContem((VerticeSubMapa)vertice);
                                ((VerticeSubMapa)vertice).setSubGrafoContido(grafo);
                            }
                        }
                    }
                }
            }
        }

        return grafoHierarquico;

        //        Grafo g = new Grafo();
        //
        //        Vertice v = null;
        //
        //        NodeList nodes_i = document.getDocumentElement().getChildNodes();
        //        for (int i = 0; i < nodes_i.getLength(); i++) {
        //            Node node_i = nodes_i.item(i);
        //            if (node_i.getNodeType() == Node.ELEMENT_NODE && ((Element)
        // node_i).getTagName().equals("vertice")) {
        //                Element vertice = (Element) node_i;
        //                if (vertice.getAttribute("tipo").equalsIgnoreCase(CRUZAMENTO)) {
        //                    v = new
        // VerticeCruzamento(Integer.parseInt(vertice.getAttribute("index")));
        //                } else if (vertice.getAttribute("tipo").equalsIgnoreCase(FINAL)) {
        //                    v = new
        // VerticeFinal(Integer.parseInt(vertice.getAttribute("index")));
        //                } else if (vertice.getAttribute("tipo").equalsIgnoreCase(PONTE)) {
        //                    v = new
        // VerticeFinal(Integer.parseInt(vertice.getAttribute("index")));
        //                } else if (vertice.getAttribute("tipo").equalsIgnoreCase(SUBMAPA)) {
        //                    v = new
        // VerticeFinal(Integer.parseInt(vertice.getAttribute("index")));
        //                } else {
        //                    // TODO ERRO!!! Tipo de v�rtice inv�lido!
        //                }
        //                v.setNome(vertice.getAttribute("nome"));
        //                v.setDescricao(vertice.getAttribute("descricao"));
        //                NodeList nodes_j = vertice.getChildNodes();
        //                for (int j = 0; j < nodes_j.getLength(); j++) {
        //                    Node node_j = nodes_j.item(j);
        //                    if (node_j.getNodeType() == Node.ELEMENT_NODE) {
        //                        Element elemento = (Element) node_j;
        //                        if (elemento.getTagName().equals("localizacao")) {
        //                            Localizacao localiz = new
        // Localizacao(Double.parseDouble(elemento.getAttribute("x")), Double
        //                                    .parseDouble(elemento.getAttribute("y")), Integer.parseInt(elemento
        //                                            .getAttribute("andar")));
        //                            v.setLocalizacao(localiz);
        //                        } else if (elemento.getTagName().equals("adjacentes")) {
        //                            NodeList nodes_k = elemento.getChildNodes();
        //                            for (int k = 0; k < nodes_k.getLength(); k++) {
        //                                Node node_k = nodes_k.item(k);
        //                                if (node_k.getNodeType() == Node.ELEMENT_NODE) {
        //                                    Element vertadj = (Element) node_k;
        //                                    int index = Integer.parseInt(vertadj.getAttribute("index"));
        //                                    int[] custos = new int[5];
        //                                    NodeList nodes_l = vertadj.getChildNodes();
        //                                    for (int l = 0; l < nodes_l.getLength(); l++) {
        //                                        Node node_l = nodes_l.item(l);
        //                                        if (node_l.getNodeType() == Node.ELEMENT_NODE) {
        //                                            Element custo = (Element) node_l;
        //                                            custos[Integer.parseInt(custo.getAttribute("tipo"))] = Integer
        //                                                    .parseInt(custo.getAttribute("valor"));
        //                                        }
        //                                    }
        //                                    VerticeAdjacente adj = new VerticeAdjacente(index, custos);
        //                                    v.addVerticeAdjacente(adj);
        //                                }
        //                            }
        //                        }
        //                    }
        //                }
        //                g.addVertice(v);
        //            }
        //        }
        //        return g;
    }
}